home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / c / pcw.zip / REORDER.C < prev    next >
C/C++ Source or Header  |  1993-09-02  |  19KB  |  441 lines

  1. /***********************************************************/
  2. /* File Id.                  Reorder.C.                    */
  3. /* Author.                   Stan Milam.                   */
  4. /* Date Written.             02/06/89.                     */
  5. /*                                                         */
  6. /*         (c) Copyright 1989, 1990 by Stan Milam          */
  7. /*                                                         */
  8. /* Comments:  The functions in this file control & maintain*/
  9. /* a list of all windows being used.  When a window is     */
  10. /* pushed it is added to the list and occupies the first   */
  11. /* position in the list.  When a window is poped it is re- */
  12. /* moved from the list, hidden and deleted.  If a window in*/
  13. /* the middle or end of the list is addressed that window  */
  14. /* is floated to the top of the list recursively.  The     */
  15. /* variable, topwnd, always points to the beginning of the */
  16. /* list.                                                   */
  17. /***********************************************************/
  18.  
  19. #if __TURBOC__ || __ZTC__
  20. #   define _fmalloc farmalloc
  21. #   define _ffree   farfree
  22. #   if __TURBOC__
  23. #      include <alloc.h>
  24. #   endif
  25. #else
  26. #   include <malloc.h>
  27. #endif
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <string.h>
  31. #include <dos.h>
  32. #include "pcw.i"
  33. #include "pcwproto.h"
  34.  
  35. #define USER   1                            /* User hidden attribute */
  36. #define SYSTEM 2                            /* System hidden attribute */
  37.  
  38. /* Function Prototypes of local functions */
  39.  
  40. static int  chk_wnds(WNDPTR *wnd);
  41. static int  hide_wnd(WNDPTR *wnd, int attribute);
  42. static int  show_wnd(WNDPTR *wnd, int attribute);
  43. static int  wnd_overlap(WNDPTR *wnd1, WNDPTR *wnd2);
  44. static void level_wnds(WNDPTR *wnd);
  45. static void remove_from_list(WNDPTR *wnd);
  46. static void reshow_wnds(WNDPTR *wnd);
  47. static void insert_first_in_list(WNDPTR *wnd);
  48. static void change_wnd_position(WNDPTR *wnd,int row,int col,int cl,int rw);
  49.  
  50. static WNDPTR *topwnd = (WNDPTR *) NULL;
  51.  
  52. /************************************************************/
  53. /*                      Get_Active_Wnd                      */
  54. /*                                                          */
  55. /* Returns the most active (top) window.  If no windows are */
  56. /* up returns NULL.                                         */
  57. /************************************************************/
  58.  
  59. WNDPTR *get_active_wnd(void) {
  60.  
  61.    return(topwnd);
  62. }
  63.  
  64. /************************************************************/
  65. /*                          Wndmove                         */
  66. /*                                                          */
  67. /* This function will handle moving a window from one place */
  68. /* on the screen to another.  It is placed in this file     */
  69. /* because it needs close proximity to the  hide/show func- */
  70. /* tions.                                                   */
  71. /************************************************************/
  72.  
  73. int wndmove(WNDPTR *wnd, int row, int col) {
  74.  
  75.    int rw, cl;
  76.  
  77.    if (!chk_video_state(&rw,&cl)) return(0);
  78.    if (wnd->hideflag == USER) {                  /* If hidden then  */
  79.       change_wnd_position(wnd,row,col,cl,rw);    /* Change position */
  80.       return(1);                                 /* And return      */
  81.    }
  82.    if (chk_wnds(wnd)) {                          /* Remove overlapping winds */
  83.       hide_wnd(wnd, SYSTEM);                     /* Hide our wnd */
  84.       reshow_wnds(wnd->back);                    /* Show overlaps */
  85.       change_wnd_position(wnd,row,col,cl,rw);    /* Change our position */
  86.       show_wnd(wnd, SYSTEM);                     /* And Show it */
  87.    }
  88.  
  89.    else {
  90.       hide_wnd(wnd, SYSTEM);                     /* No overlaps so hide */
  91.       change_wnd_position(wnd,row,col,cl,rw);    /* Change position */
  92.       show_wnd(wnd, SYSTEM);                     /* And show it     */
  93.    }
  94.    remove_from_list(wnd);                        /* Move wnd to first */
  95.    insert_first_in_list(wnd);                    /* In list */
  96.    level_wnds(topwnd);                           /* Relevel all windows */
  97.    return(1);                                    /* Return  */
  98. }
  99.  
  100. /***********************************************************/
  101. /*                    Change_Wnd_Position                  */
  102. /*                                                         */
  103. /* This function calculates the new position of a window.  */
  104. /* Checks that it will be in bounds of screen and adjusts  */
  105. /* if it is not.                                           */
  106. /***********************************************************/
  107.  
  108. static void change_wnd_position(WNDPTR *wnd,int row,int col,int cl,int rw) {
  109.  
  110.    int rows, cols;
  111.  
  112.    rows = (wnd->lrow - wnd->urow);            /* Calc total rows */
  113.    cols = (wnd->lcol - wnd->ucol);            /* Same for cols   */
  114.  
  115.    if (row < 1) row = 1;
  116.    if (col < 1) col = 1;
  117.  
  118.    if ((col + cols) >  cl) {                  /* Is it in bounds */
  119.       cl = (col + cols) - cl;
  120.       col = col - cl;
  121.    }
  122.  
  123.    if ((row + rows) > rw) {                   /* Is it in bounds? */
  124.       rw = (row + rows) - rw;                 /* No - Adjust the rows */
  125.       row= row - rw;
  126.    }
  127.  
  128.    wnd->urow = row;                           /* Save in wnd structure */
  129.    wnd->ucol = col;
  130.    wnd->lrow = row + rows;
  131.    wnd->lcol = col + cols;
  132. }
  133.  
  134. /************************************************************/
  135. /*                          Re_Order                        */
  136. /*                                                          */
  137. /* This function is the main driver for the window list     */
  138. /* management routines.  Its job, depending on the action to*/
  139. /* be taken is to handle the logic of managing how the      */
  140. /* windows are ordered visibly, and how they are ordered    */
  141. /* logically in the window list.                            */
  142. /************************************************************/
  143.  
  144. void re_order(WNDPTR *wnd, int action) {
  145.  
  146.    switch(action) {
  147.       case NORMAL :                         /* Bring window to surface */
  148.          if (wnd->level == 1) return;       /* If first in list-forget it */
  149.          if (chk_wnds(wnd)) {               /* If window overlap then */
  150.             hide_wnd(wnd, SYSTEM);          /* Hide our window     */
  151.             reshow_wnds(wnd->back);         /* Show those that were hid */
  152.             show_wnd(wnd, SYSTEM);          /* Put ours on top */
  153.          }
  154.          remove_from_list(wnd);             /* Remove from window list */
  155.          insert_first_in_list(wnd);         /* Make it the logical first */
  156.          break;
  157.  
  158.       case PUSH :                           /* Adding a new window to list */
  159.          insert_first_in_list(wnd);         /* Insert it first */
  160.          break;                             /* Over & Out! */
  161.  
  162.       case POP :                            /* For pops */
  163.          if (wnd->hideflag) {               /* If window hidden */
  164.             remove_from_list(wnd);          /* Remove it from list */
  165.             break;                          /* And get out */
  166.          }
  167.          if (wnd->level == 1) {             /* If first in list */
  168.             remove_from_list(wnd);          /* Remove it */
  169.             hide_wnd(wnd, SYSTEM);          /* Hide it */
  170.          }
  171.          else {
  172.             if (chk_wnds(wnd)) {            /* If someone overlaps */
  173.                 hide_wnd(wnd, SYSTEM);      /* Hide ours */
  174.                 reshow_wnds(wnd->back);     /* Reshow other windows */
  175.             }
  176.             else hide_wnd(wnd, SYSTEM);     /* No overlaps - so hide */
  177.             remove_from_list(wnd);          /* Remove from list */
  178.          }
  179.          break;
  180.  
  181.       case HIDE :
  182.          if (wnd->level == 1) {             /* If first window... */
  183.             hide_wnd(wnd, USER);            /* Hide it with user attribute */
  184.             return;                         /* and return */
  185.          }
  186.          if (chk_wnds(wnd)) {               /* Remove overlaps if any */
  187.             hide_wnd(wnd, USER);            /* Hide window with user attr */
  188.             reshow_wnds(wnd->back);         /* Reshow the overlaps */
  189.          }
  190.          else {
  191.             hide_wnd(wnd, USER);            /* No overlaps so just hide */
  192.             return;                         /* Return */
  193.          }
  194.          break;
  195.  
  196.       case SHOW :
  197.          if (wnd->hideflag != USER)         /* Do not try to show a  */
  198.             return;                         /* Window not hidden */
  199.          show_wnd(wnd, USER);               /* Show the window   */
  200.          remove_from_list(wnd);             /* Put the window first in */
  201.          insert_first_in_list(wnd);         /* List                    */
  202.          break;
  203.  
  204.    }
  205.    level_wnds(topwnd);                      /* Relevel the windows. */
  206. }
  207.  
  208.  
  209. /************************************************************/
  210. /*                     Remove_From_List                     */
  211. /*                                                          */
  212. /* This routine will remove a window from the window list.  */
  213. /* The logic is most likely more complicated than needed but*/
  214. /* better safe than sorry when worrying about null pointer  */
  215. /* assignments.                                             */
  216. /************************************************************/
  217.  
  218. static void remove_from_list(WNDPTR *wnd) {
  219.  
  220.    if (wnd->back == NULL) {                    /* Means its the top */
  221.       if (wnd->next == NULL)                   /* Means its the only one */
  222.          topwnd = (WNDPTR *) NULL;             /* Set the top to NULL */
  223.       else {
  224.          wnd->next->back = (WNDPTR *) NULL;    /* Set the back to NULL */
  225.          topwnd = wnd->next;                   /* Make the next on top */
  226.       }
  227.    }
  228.    else {                                      /* Its in middle or at end */
  229.       if (wnd->next == NULL)                   /* Its the end */
  230.          wnd->back->next = (WNDPTR *) NULL;    /* Cut it out of list */
  231.       else {                                   /* Its in the middle */
  232.          wnd->next->back = wnd->back;          /* Remove & reset all */
  233.          wnd->back->next = wnd->next;          /* the pointers */
  234.       }
  235.    }
  236. }
  237.  
  238. /************************************************************/
  239. /*                   Insert_First_In_List                   */
  240. /*                                                          */
  241. /* The name says it all.  A little logic to protect against */
  242. /* the dreaded "Null Pointer Assignment" message.           */
  243. /************************************************************/
  244. static void insert_first_in_list(WNDPTR *wnd) {
  245.  
  246.       wnd->next     = (WNDPTR *) topwnd;    /* Insert it first in list */
  247.       wnd->back     = (WNDPTR *) NULL;      /* Back always set to NULL */
  248.       if (topwnd != NULL)                   /* If topwnd = NULL then */
  249.          topwnd->back = wnd;                /* NO assignment PLEASE  */
  250.       topwnd        = wnd;                  /* Make our wnd first    */
  251. }
  252.  
  253. /*************************************************************/
  254. /*                           Chk_Wnds                        */
  255. /*                                                           */
  256. /* This routine recursively determines if a window is over-  */
  257. /* lapping another.  If a window is found to be overlapping  */
  258. /* it must hide that window, but first it must determine if  */
  259. /* a window above it is overlapping so it calls itself.      */
  260. /* It will work its way down - and up - the list removing    */
  261. /* all overlapping windows.                                  */
  262. /*************************************************************/
  263.  
  264. static int chk_wnds(WNDPTR *wnd) {
  265.  
  266.    WNDPTR *wrkwnd;
  267.    int    overlap;
  268.  
  269.    wrkwnd = topwnd;                          /* Start with top window */
  270.    overlap= 0;                               /* Set local auto to false */
  271.    while (wrkwnd->level < wnd->level) {      /* While 1 less than level */
  272.       if (!wrkwnd->hideflag) {               /* If its hidden forget it */
  273.          if (wnd_overlap(wrkwnd, wnd)) {     /* If they overlap */
  274.             overlap = 1;                     /* Set our switch */
  275.             chk_wnds(wrkwnd);                /* Recurse with new window */
  276.             hide_wnd(wrkwnd, SYSTEM);        /* Finally hide it */
  277.          }
  278.       }
  279.       wrkwnd = wrkwnd->next;                 /* Grab next window */
  280.    }
  281.    return (overlap);                         /* Return our switch setting */
  282. }
  283.  
  284. /************************************************************/
  285. /*                        Reshow_Wnds                       */
  286. /*                                                          */
  287. /* This function reshows any windows we had to hide along   */
  288. /* the way. It runs thru the list backwards to the beginning*/
  289. /************************************************************/
  290.  
  291. static void reshow_wnds(WNDPTR *wnd) {
  292.  
  293.    while (wnd) {                            /* Run Backwards thru the */
  294.        if (wnd->hideflag != USER)            /* If user attr skip */
  295.           show_wnd(wnd, SYSTEM);             /* List showing windows */
  296.        wnd = wnd->back;                      /* We pulled off */
  297.    }
  298. }
  299. /* */
  300. /************************************************************/
  301. /*                        Level_Wnds                        */
  302. /*                                                          */
  303. /* This funtion runs thru the list from the beginning and   */
  304. /* reassignes level values to each window after and inser-  */
  305. /* tion or deletion.                                        */
  306. /************************************************************/
  307.  
  308. static void level_wnds(WNDPTR *wnd) {
  309.  
  310.    int  i = 1;
  311.    WNDPTR *wrkwnd;
  312.  
  313.    wrkwnd = wnd;
  314.    while (wrkwnd) {                     /* While window pointer not NULL */
  315.         wrkwnd->level = i++;            /* Assign a new level number */
  316.         wrkwnd = wrkwnd->next;          /* Get next window */
  317.    }
  318. }
  319.  
  320. /************************************************************/
  321. /*                         Hide_Wnd                         */
  322. /*                                                          */
  323. /* This routine will hide a specified window with one of two*/
  324. /* attributes, USER & SYSTEM.  The system attribute means   */
  325. /* the window system is hiding the window for its own       */
  326. /* purposes and is a temporary hide while the user attribute*/
  327. /* means the user wanted to hide the window and leave it    */
  328. /* hidden until it is desired to be shown.  USER overrides  */
  329. /* SYSTEM, meaning if the system is running thru the list   */
  330. /* showing all SYSTEM hidden windows the USER hidden will   */
  331. /* be ignored.                                              */
  332. /************************************************************/
  333.  
  334. static int hide_wnd(WNDPTR *wnd, int attribute) {
  335.  
  336.    int  rows, cols, page, pagesize;
  337.    unsigned offset, scrnseg;
  338.    int far *scrnptr;
  339.  
  340.    if (wnd->hideflag) return(1);             /* Can't hide again */
  341.    if (wnd->wbuffer  == (char far *) NULL)
  342.       return(0);
  343.  
  344.    cols = (wnd->lcol - wnd->ucol) + 1;       /* Calc total cols */
  345.    rows = (wnd->lrow - wnd->urow) + 1;       /* And rows */
  346.    page = wnd->page;
  347.  
  348.    if (wnd->wsave == (char far *) NULL) {
  349.       wnd->wsave = (char far *) _fmalloc((rows * cols) * 2);
  350.       if (wnd->wsave == (char far *) NULL)
  351.          return(0);
  352.    }
  353.  
  354.    pagesize = getpagesize();
  355.    scrnseg  = getscrnseg();
  356.    offset   = MK_SCRNOFF(wnd->urow,wnd->ucol);
  357.    scrnptr  = (int far *) MK_FP(scrnseg, offset);
  358.  
  359.    SaveScrn(rows, cols, scrnptr, wnd->wsave);
  360.    RestoreScrn(rows, cols, scrnptr, wnd->wbuffer);
  361.    wnd->hideflag = attribute;
  362.    return(1);
  363. }
  364.  
  365. /************************************************************/
  366. /*                         Show_Wnd                         */
  367. /*                                                          */
  368. /* This function will show the windows that were hidden.    */
  369. /* If the show is with attribute SYSTEM and the window was  */
  370. /* hidden with USER we will bypass.                         */
  371. /************************************************************/
  372.  
  373. static int show_wnd(WNDPTR *wnd, int attribute) {
  374.  
  375.     int rows, cols, page, pagesize;
  376.     unsigned scrnseg, offset;
  377.     int far *scrnptr;
  378.  
  379.     if (wnd->wbuffer == NULL || wnd->wsave == NULL)  /* Exit if not */
  380.        return(0);                                    /* Ever allocated */
  381.  
  382.     if (wnd->hideflag != attribute)                  /* Can't show if */
  383.        return(0);                                    /* Attr don't match */
  384.  
  385.     wnd->hideflag = 0;                               /* Reset hideflag */
  386.     rows = (wnd->lrow - wnd->urow) + 1;              /* Calc total rows */
  387.     cols = (wnd->lcol - wnd->ucol) + 1;              /* And Cols */
  388.     page = wnd->page;                                /* Get the scrn page */
  389.  
  390.     scrnseg = getscrnseg();                          /* Get scrn segment */
  391.     pagesize= getpagesize();                         /* get pagesize */
  392.     offset  = MK_SCRNOFF(wnd->urow,wnd->ucol);       /* Calc offset */
  393.     scrnptr = (int far *) MK_FP(scrnseg, offset);    /* Make a far pointer */
  394.  
  395.     SaveScrn(rows, cols, scrnptr, wnd->wbuffer);     /* Save whats there */
  396.     RestoreScrn(rows, cols, scrnptr, wnd->wsave);    /* Put the wnd down */
  397.     return(1);                                       /* Return */
  398. }
  399.  
  400.  
  401. /************************************************************/
  402. /*                        Wnd_Overlap                       */
  403. /*                                                          */
  404. /* This routine determines if two windows overlap the same  */
  405. /* portion of the screen.  It is a bit difficult to tell how*/
  406. /* it works.  I had to draw myself some pictures of over-   */
  407. /* lapping windows to figure it out.                        */
  408. /************************************************************/
  409.  
  410. static int wnd_overlap(WNDPTR *wnd1, WNDPTR *wnd2) {
  411.  
  412.     if (wnd1->page != wnd2->page)          /* If not in same page */
  413.        return(0);                          /* they can't overlap  */
  414.  
  415.     if (((wnd2->ucol >= wnd1->ucol) && (wnd2->ucol <= wnd1->lcol)) &&
  416.        (((wnd2->urow >= wnd1->urow) && (wnd2->urow <= wnd1->lrow)) ||
  417.         ((wnd2->lrow >= wnd1->urow) && (wnd2->lrow <= wnd1->lrow))))
  418.             return(1);
  419.  
  420.     if (((wnd2->lcol >= wnd1->ucol) && (wnd2->lcol <= wnd1->lcol)) &&
  421.        (((wnd2->urow >= wnd1->urow) && (wnd2->urow <= wnd1->lrow)) ||
  422.         ((wnd2->lrow >= wnd1->urow) && (wnd2->lrow <= wnd1->lrow))))
  423.             return(1);
  424.  
  425.     if (((wnd1->ucol >= wnd2->ucol) && (wnd1->lcol <= wnd2->lcol)) &&
  426.        (((wnd1->urow >= wnd2->urow) && (wnd1->urow <= wnd2->lrow)) ||
  427.         ((wnd1->lrow >= wnd2->urow) && (wnd1->lrow <= wnd2->lrow))))
  428.             return(1);
  429.  
  430.     if (((wnd1->urow >= wnd2->urow) && (wnd1->lrow <= wnd2->lrow)) &&
  431.        (((wnd1->ucol >= wnd2->ucol) && (wnd1->ucol <= wnd2->lcol)) ||
  432.         ((wnd1->lcol >= wnd2->ucol) && (wnd1->lcol <= wnd2->lcol))))
  433.             return(1);
  434.  
  435.     if ((wnd1->ucol > wnd2->ucol && wnd1->lcol < wnd2->lcol) &&
  436.         (wnd1->urow > wnd2->urow && wnd1->lrow < wnd2->lrow))
  437.             return(1);
  438.  
  439.     return(0);
  440. }
  441.